#pragma once
#include "DXContext.h"
#include "enums.h"
#include "States.h"
#include "Texture2D.h"
#include "DataArray.h"

namespace DXBase
{
	namespace D3D
	{
		ref class PixelShader;
		ref class VertexShader;
		ref class Texture2D;
		interface class IShape;
		ref class Buffer;
		ref class VetexLayout;

		ref class SamplerState;
		ref class RasterizerState;
		ref class BlendState;
		ref class DepthStencilState;

		// a class to render arbitrary DirectX
		[Windows::Foundation::Metadata::WebHostHidden]
		public ref class D3DGraphic sealed
		{
		public:
			D3DGraphic(DXContext^ ctxt);
			property DXContext^ Context { DXContext^ get() { return mContext; } }

			void Clear(Windows::UI::Color bg);
			void Flush();

			void SetStateSampler(D3D::SamplerState^ state);
			void SetStateSampler(UINT slot, D3D::SamplerState^ state);
			void SetStateSamplers(UINT slot, const Platform::Array<D3D::SamplerState^>^ states);
			void SetStateRasterizer(D3D::RasterizerState^ state);
			void SetStateBlend(D3D::BlendState^ state) { SetStateBlend(state, vector4(1,1,1,1), 0xFFFFFFFF); }
			void SetStateBlend(D3D::BlendState^ state, float4 blendFactor, uint32 mask);
			void SetStateDepthStencil(D3D::DepthStencilState^ state) { SetStateDepthStencil(state, 0); }
			void SetStateDepthStencil(D3D::DepthStencilState^ state, UINT stencilRef);

			property D3D::PixelShader^ PixelShader
			{
				D3D::PixelShader^ get() { return pixelShader; }
				void set(D3D::PixelShader^ value);
			}
			property D3D::VertexShader^ VertexShader
			{
				D3D::VertexShader^ get() { return vertexShader; }
				void set(D3D::VertexShader^ value);
			}

			void SetShaderResource(D3D::ShaderType sdt, D3D::IResource^ res);
			void SetShaderResource(UINT slot, D3D::ShaderType sdt, D3D::IResource^ res);
			void SetShaderResources(UINT slot, D3D::ShaderType sdt, const Platform::Array<D3D::IResource^>^ res);

			void SetConstantBuffer(unsigned slot, D3D::ShaderType sdt, D3D::Buffer^ buf);
			void SetConstantBuffers(unsigned slot, D3D::ShaderType sdt, Windows::Foundation::Collections::IIterable<D3D::Buffer^>^ buf);

			property D3D::IShape^ Shape 
			{
				D3D::IShape^ get() { return shape; }
				void set(D3D::IShape^ value);
			}

			void Draw();
			void Draw(UINT start, UINT count);
			void DrawIndexed();
			void DrawIndexed(UINT count, UINT baseIndex, UINT baseVertex);

		private:
			DXContext^ mContext;

			// state
			D3D::PixelShader^ pixelShader;
			D3D::VertexShader^ vertexShader;
			D3D::IShape^ shape;
		};
	}
}